
/**
  ******************************************************************************
  * Copyright 2021 The Microbee Authors. All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  * 
  * @file       mb_arming.h
  * @author     baiyang
  * @date       2022-11-17
  ******************************************************************************
  */

#pragma once

#ifdef __cplusplus
extern "C"{
#endif

/*----------------------------------include-----------------------------------*/
#include <stdbool.h>
#include <stdint.h>

#include <rc_channel/rc_channel.h>
#include <common/gp_defines.h>
#include <gcs_mavlink/gcs.h>
/*-----------------------------------macro------------------------------------*/

/*----------------------------------typedef-----------------------------------*/
enum ArmingChecks {
    ARMING_CHECK_ALL         = (1U << 0),
    ARMING_CHECK_BARO        = (1U << 1),
    ARMING_CHECK_COMPASS     = (1U << 2),
    ARMING_CHECK_GPS         = (1U << 3),
    ARMING_CHECK_INS         = (1U << 4),
    ARMING_CHECK_PARAMETERS  = (1U << 5),
    ARMING_CHECK_RC          = (1U << 6),
    ARMING_CHECK_VOLTAGE     = (1U << 7),
    ARMING_CHECK_BATTERY     = (1U << 8),
    ARMING_CHECK_AIRSPEED    = (1U << 9),
    ARMING_CHECK_LOGGING     = (1U << 10),
    ARMING_CHECK_SWITCH      = (1U << 11),
    ARMING_CHECK_GPS_CONFIG  = (1U << 12),
    ARMING_CHECK_SYSTEM      = (1U << 13),
    ARMING_CHECK_MISSION     = (1U << 14),
    ARMING_CHECK_RANGEFINDER = (1U << 15),
    ARMING_CHECK_CAMERA      = (1U << 16),
    ARMING_CHECK_AUX_AUTH    = (1U << 17),
    ARMING_CHECK_VISION      = (1U << 18),
    ARMING_CHECK_FFT         = (1U << 19),
};

enum ArmingMethod {
    ARMING_METHOD_RUDDER = 0,
    ARMING_METHOD_MAVLINK = 1,
    ARMING_METHOD_AUXSWITCH = 2,
    ARMING_METHOD_MOTORTEST = 3,
    ARMING_METHOD_SCRIPTING = 4,
    ARMING_METHOD_TERMINATION = 5, // only disarm uses this...
    ARMING_METHOD_CPUFAILSAFE = 6, // only disarm uses this...
    ARMING_METHOD_BATTERYFAILSAFE = 7, // only disarm uses this...
    ARMING_METHOD_SOLOPAUSEWHENLANDED = 8, // only disarm uses this...
    ARMING_METHOD_AFS = 9, // only disarm uses this...
    ARMING_METHOD_ADSBCOLLISIONACTION = 10, // only disarm uses this...
    ARMING_METHOD_PARACHUTE_RELEASE = 11, // only disarm uses this...
    ARMING_METHOD_CRASH = 12, // only disarm uses this...
    ARMING_METHOD_LANDED = 13, // only disarm uses this...
    ARMING_METHOD_MISSIONEXIT = 14, // only disarm uses this...
    ARMING_METHOD_FENCEBREACH = 15, // only disarm uses this...
    ARMING_METHOD_RADIOFAILSAFE = 16, // only disarm uses this...
    ARMING_METHOD_DISARMDELAY = 17, // only disarm uses this...
    ARMING_METHOD_GCSFAILSAFE = 18, // only disarm uses this...
    ARMING_METHOD_TERRRAINFAILSAFE = 19, // only disarm uses this...
    ARMING_METHOD_FAILSAFE_ACTION_TERMINATE = 20, // only disarm uses this...
    ARMING_METHOD_TERRAINFAILSAFE = 21, // only disarm uses this...
    ARMING_METHOD_MOTORDETECTDONE = 22, // only disarm uses this...
    ARMING_METHOD_BADFLOWOFCONTROL = 23, // only disarm uses this...
    ARMING_METHOD_EKFFAILSAFE = 24, // only disarm uses this...
    ARMING_METHOD_GCS_FAILSAFE_SURFACEFAILED = 25, // only disarm uses this...
    ARMING_METHOD_GCS_FAILSAFE_HOLDFAILED = 26, // only disarm uses this...
    ARMING_METHOD_TAKEOFFTIMEOUT = 27, // only disarm uses this...
    ARMING_METHOD_AUTOLANDED = 28, // only disarm uses this...
    ARMING_METHOD_PILOT_INPUT_FAILSAFE = 29, // only disarm uses this...
    ARMING_METHOD_TOYMODELANDTHROTTLE = 30, // only disarm uses this...
    ARMING_METHOD_TOYMODELANDFORCE = 31, // only disarm uses this...
    ARMING_METHOD_LANDING = 32, // only disarm uses this...
    ARMING_METHOD_DEADRECKON_FAILSAFE = 33, // only disarm uses this...
    ARMING_METHOD_UNKNOWN = 100,
};

enum ArmingRequired {
    ARMING_REQUIRED_NO           = 0,
    ARMING_REQUIRED_YES_MIN_PWM  = 1,
    ARMING_REQUIRED_YES_ZERO_PWM = 2
};

// rudder arming support
enum RudderArming {
    ARMING_RUDDER_IS_DISABLED  = 0, // DISABLED leaks in from vehicle defines.h
    ARMING_RUDDER_ARMONLY   = 1,
    ARMING_RUDDER_ARMDISARM = 2
};

// enum for ARMING_OPTIONS parameter
enum ArmingOption {
    ARMING_OPTION_DISABLE_PREARM_DISPLAY   = (1U << 0),
};

enum MIS_ITEM_CHECK {
    ARMING_MIS_ITEM_CHECK_LAND          = (1 << 0),
    ARMING_MIS_ITEM_CHECK_VTOL_LAND     = (1 << 1),
    ARMING_MIS_ITEM_CHECK_DO_LAND_START = (1 << 2),
    ARMING_MIS_ITEM_CHECK_TAKEOFF       = (1 << 3),
    ARMING_MIS_ITEM_CHECK_VTOL_TAKEOFF  = (1 << 4),
    ARMING_MIS_ITEM_CHECK_RALLY         = (1 << 5),
    ARMING_MIS_ITEM_CHECK_RETURN_TO_LAUNCH = (1 << 6),
    ARMING_MIS_ITEM_CHECK_MAX
};

enum ArmingAuxAuthStates {
    ARMING_AUX_NO_RESPONSE = 0,
    ARMING_AUX_AUTH_FAILED,
    ARMING_AUX_AUTH_PASSED
};

typedef struct mb_arming* mb_arming_t;
typedef const struct mb_arming* mb_arming_const_t;
typedef struct mb_arming_ops* mb_arming_ops_t;

struct mb_arming {
    mb_arming_ops_t            ops;

    // Parameters
    Param_int8                 require;
    Param_int32                checks_to_perform;      // bitmask for which checks are required
    Param_float                accel_error_threshold;
    Param_int8                 _rudder_arming;
    Param_int32                _required_mission_items;
    Param_int32                _arming_options;

    // internal members
    bool                    armed;
    uint32_t                last_accel_pass_ms;
    uint32_t                last_gyro_pass_ms;

    // method that was last used for disarm; invalid unless the
    // vehicle has been disarmed at least once.
    enum ArmingMethod       _last_disarm_method;  // default, ARMING_METHOD_UNKNOWN;

    uint32_t                last_prearm_display_ms;  // last time we send statustexts for prearm failures
    bool                    running_arming_checks;  // true if the arming checks currently being performed are being done because the vehicle is trying to arm the vehicle
};

struct mb_arming_ops {
    bool (*arm)(enum ArmingMethod method, bool do_arming_checks);          // bool do_arming_checks=true
    bool (*disarm)(enum ArmingMethod method, bool do_disarm_checks);       // bool do_disarm_checks=true

    // pre_arm_checks() is virtual so it can be modified in a vehicle specific subclass
    bool (*pre_arm_checks)(bool report);

    // some arming checks have side-effects, or require some form of state
    // change to have occurred, and thus should not be done as pre-arm
    // checks.  Those go here:
    bool (*arm_checks)(enum ArmingMethod method);

    bool (*barometer_checks)(bool report);
    bool (*ins_checks)(bool report);
    bool (*gps_checks)(bool report);
    bool (*board_voltage_checks)(bool report);
    bool (*rc_calibration_checks)(bool report);
    bool (*mission_checks)(bool report);

    // expected to return true if the terrain database is required to have
    // all data loaded
    bool (*terrain_database_required)();

    bool (*system_checks)(bool report);
    bool (*proximity_checks)(bool report);

    // mandatory checks that cannot be bypassed.  This function will only be called if ARMING_CHECK is zero or arming forced
    bool (*mandatory_checks)(bool report);
};

/*----------------------------------variable----------------------------------*/

/*-------------------------------------os-------------------------------------*/

/*----------------------------------function----------------------------------*/
void mb_arming_ctor(mb_arming_t arming, mb_arming_ops_t ops);

// get singleton instance
mb_arming_t mb_arming_get_singleton();

void mb_arming_init();
void mb_arming_update(void);

enum ArmingRequired mb_arming_required();
bool mb_arming_rc_in_calibration_check(bool report);

void mb_arming_check_failed(bool report, const char *fmt, ...);
void mb_arming_check_failed2(const enum ArmingChecks check, bool report, const char *fmt, ...);

bool mb_arming_is_armed();
bool mb_arming_is_armed_and_safety_off();
uint32_t mb_arming_get_enabled_checks();
bool mb_arming_check_enabled(const enum ArmingChecks check);

bool mb_arming_rc_arm_checks(enum ArmingMethod method);

bool mb_arming_ins_accels_consistent();
bool mb_arming_ins_gyros_consistent();
bool mb_arming_rc_checks_copter_sub(const bool display_failure, rc_channel_const_t channels[4]);
bool mb_arming_disarm_switch_checks(bool display_failure);
bool mb_arming_hardware_safety_check(bool report);
bool mb_arming_compass_checks(bool report);
bool mb_arming_airspeed_checks(bool report);
bool mb_arming_battery_checks(bool report);
bool mb_arming_manual_transmitter_checks(bool report);
bool mb_arming_servo_checks(bool report);
enum RudderArming mb_arming_get_rudder_arming_type();

/// ops
bool mb_armingArm(enum ArmingMethod method, const bool do_arming_checks);
bool mb_armingDisarm(const enum ArmingMethod method, bool do_disarm_checks);
bool mb_arming_ArmChecks(enum ArmingMethod method);
bool mb_arming_MandatoryChecks(bool report);
bool mb_arming_PreArmChecks(bool report);
bool mb_arming_BarometerChecks(bool report);
bool mb_arming_InsChecks(bool report);
bool mb_arming_GpsChecks(bool report);
bool mb_arming_BoardVoltageChecks(bool report);
bool mb_arming_RcCalibrationChecks(bool report);
bool mb_arming_MissionChecks(bool report);
bool mb_arming_TerrainDatabaseRequired();
bool mb_arming_SystemChecks(bool report);
bool mb_arming_ProximityChecks(bool report);

void mb_arming_log_write_arm(const bool forced, const enum ArmingMethod method);
void mb_arming_log_write_disarm(const bool forced, const enum ArmingMethod method);

bool mb_arming_arm(enum ArmingMethod method, bool do_arming_checks);
bool mb_arming_disarm(enum ArmingMethod method, bool do_disarm_checks);
bool mb_arming_pre_arm_checks(bool report);
bool mb_arming_arm_checks(enum ArmingMethod method);
bool mb_arming_barometer_checks(bool report);
bool mb_arming_ins_checks(bool report);
bool mb_arming_gps_checks(bool report);
bool mb_arming_board_voltage_checks(bool report);
bool mb_arming_rc_calibration_checks(bool report);
bool mb_arming_mission_checks(bool report);
bool mb_arming_terrain_database_required();
bool mb_arming_system_checks(bool report);
bool mb_arming_proximity_checks(bool report);
bool mb_arming_mandatory_checks(bool report);
/*------------------------------------test------------------------------------*/

#ifdef __cplusplus
}
#endif



